#ifndef CWINDOWBASE_HPP
#define CWINDOWBASE_HPP

#include <windows.h>
#include <strsafe.h>
#include <commctrl.h>

class CWindowBase
{
public:
    ~CWindowBase() {}
    CWindowBase() {}
    CWindowBase(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        Register(lpszClassName, hInstance);
    }
    CWindowBase(const CWindowBase &) = delete;
    CWindowBase &operator=(const CWindowBase &) = delete;
    LRESULT Register(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        m_wcex = {0};
        m_wcex.cbSize = sizeof(WNDCLASSEX);
        m_wcex.cbClsExtra = 0;                                      // 类的额外内存
        m_wcex.cbWndExtra = 0;                                      // 窗口额外内存
        m_wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 背景
        m_wcex.hCursor = LoadCursor(NULL, IDC_ARROW);               // 光标 第一个为NULL代表使用系统提供的光标
        m_wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);             // 图标 第一个为NULL代表使用系统提供的图标
        m_wcex.hInstance = hInstance;                               // 应用程序实例句柄
        m_wcex.lpfnWndProc = CWindowBase::WndProc;                  // 回调函数
        m_wcex.lpszClassName = lpszClassName;                       // 窗口类名称
        m_wcex.lpszMenuName = NULL;                                 // 菜单名称
        m_wcex.style = CS_HREDRAW | CS_VREDRAW;                     // 显示风格
        m_hInstance = hInstance;
        if (!RegisterClassEx(&m_wcex))
        {
            MessageBox(NULL, TEXT("Failed to register child window class"), TEXT("Error"), MB_OK | MB_ICONERROR);
            return -1;
        }
        return 0;
    }
    LRESULT Create(HWND hParent, LPRECT lpRect, LPCTSTR szWindowName)
    {
        // Create the child window
        RECT rect;
        if (!lpRect)
        {
            GetClientRect(hParent, &rect);
            lpRect = &rect;
            // MessageBox(NULL, TEXT("lpRect"), TEXT("lpRect"), MB_OK);
        }
        m_hWnd = CreateWindow(m_wcex.lpszClassName, szWindowName, WS_CHILD | WS_VISIBLE,
                              lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
                              hParent, NULL, m_hInstance, this);
        m_hParent = hParent;
        SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
        return 0;
    }
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        CWindowBase *pThis = (CWindowBase *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
        if (pThis)
        {
            return pThis->WindowProc(hWnd, uMsg, wParam, lParam);
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            HPEN hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
            HPEN holdPen = (HPEN)SelectObject(hdc, hPen);
            HBRUSH hBrush = CreateSolidBrush(RGB(200, 255, 200));
            HBRUSH holdBrush = (HBRUSH)SelectObject(hdc, hBrush);

            RECT rect;
            GetClientRect(hWnd, &rect);
            Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);

            SelectObject(hdc, holdPen);
            SelectObject(hdc, holdBrush);

            DeleteObject(hPen);
            DeleteObject(hBrush);
            EndPaint(hWnd, &ps);
            break;
        }
        case WM_COMMAND:
        {
            TCHAR szText[MAX_PATH] = {0};
            StringCchPrintf(szText, MAX_PATH, TEXT("xPos: %d, yPos: %d"), LOWORD(wParam), HIWORD(wParam));

            HDC hdc = GetDC(hWnd);
            HPEN hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
            HPEN holdPen = (HPEN)SelectObject(hdc, hPen);
            TextOut(hdc, 0, 0, szText, wcslen(szText));
            SelectObject(hdc, holdPen);
            ReleaseDC(hWnd, hdc);
            break;
        }
        case WM_SIZE:
        {
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        }
        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
            break;
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
        default:
        {
        }
        }
        return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
    }

public:
    HWND m_hWnd;
    HWND m_hParent;
    WNDCLASSEX m_wcex;
    HINSTANCE m_hInstance;
};

#endif